<!--
 * @Description: 顶部菜单栏布局
 * [/horizon-frontend/src/components/SettingDrawer/themeColor.js -- topLayoutMenuStyle()]: 头部菜单颜色的hack处理
 * @Author: wangfuwei
 * @Date: 2020-12-02 00:22:07
 * @LastEditors: wangfuwei
 * @LastEditTime: 2021-04-25 23:11:34
 * @FilePath: /horizon-frontend/src/layouts/TopLayout.vue
-->
<template>
  <div id="top-layout">
    <a-layout>
      <a-layout-header>
        <!-- 左侧菜单栏 -->
        <div class="left-info">
          <a-dropdown class="drop-down-menu" v-model="dropdownShow" :trigger="['click']" @visibleChange="visible => (dropdownClass = visible ? 'dropdown' : 'up')" overlayClassName="drop-shortcut">
            <div>
              <div class="logo">
                <img :src="logo" />
              </div>
              <span>{{ $t("title") }}</span>
              <a-icon type="down" :class="dropdownClass" />
            </div>
            <!-- 我的常用 -->
            <shortcut style="width:100%" slot="overlay" />
          </a-dropdown>

          <!-- 系统应用 -->
          <a-menu mode="horizontal" :selectedKeys="selectedKeys" :style="{ lineHeight: '52px', flex: 'auto', overflow: 'hidden' }">
            <a-menu-item v-for="item in openApps" :key="item.code" :class="{ divider: item.code === 'divider', 'toplayout-menu-item': true }">
              <!-- 分隔符 -->
              <div v-if="item.code === 'divider'"></div>
              <!-- 一级菜单 -->
              <a v-if="item.code !== 'divider'" href="javascript:void(0)" @click="toApp(item.code)">{{ $t(`${item.fdId}.name`) }}</a>
              <!-- 非全局应用显示锁定和关闭图标 -->
              <span v-if="!item.global && item.code !== 'divider'" style="display:none" class="lockable-icon">
                <a-icon class="icon close-icon" v-if="!item.locked" type="close" @click.prevent.stop="closeApp(item)" />
                <span class="icon lock-icon">
                  <a-icon v-if="!item.locked" @click="lockLoading ? '' : lock(item, true)" :type="lockLoading ? 'loading' : 'unlock'" />
                  <a-icon v-if="item.locked" @click="lockLoading ? '' : lock(item, false)" :type="lockLoading ? 'loading' : 'lock'" />
                </span>
              </span>
            </a-menu-item>
          </a-menu>
        </div>

        <!-- 右侧用户信息栏 -->
        <div class="right-info">
          <div class="user" @click="$refs.settingDrawer.showDrawer()">
            <a-avatar size="large" :src="avatar" icon="user" />
          </div>
        </div>
      </a-layout-header>

      <!-- 正文区域 -->
      <a-layout-content class="top-layout-content">
        <slot> </slot>
      </a-layout-content>
    </a-layout>

    <!-- 侧边抽屉 -->
    <setting-drawer ref="settingDrawer" />
  </div>
</template>
<script>
import Shortcut from "./Shortcut";
import SettingDrawer from "@/components/SettingDrawer";
import { appMixin } from "@/utils/mixin";
import { lockApp } from "@/api/system";

export default {
  name: "TopLayout",
  mixins: [appMixin],
  components: { Shortcut, SettingDrawer },

  data() {
    return {
      selectedKeys: [],
      dropdownClass: "up",
      dropdownShow: false,
      lockLoading: false,
    };
  },

  computed: {
    openApps() {
      return [...this.globalApps, ...this.lockedApps];
    },
  },

  methods: {
    /**
     * 根据编码查找App对象
     */
    findApp(appCode) {
      let rtnVal = null;
      this.globalApps.some(app => {
        if (app.code === appCode) {
          rtnVal = app;
          return true;
        }
      });
      if (rtnVal) return rtnVal;

      this.cloudApps.some(cloud => {
        cloud.children.some(app => {
          if (app.code === appCode) {
            rtnVal = app;
            return true;
          }
        });
        if (rtnVal) return true;
      });
      return rtnVal;
    },

    /**
     * 打开应用
     */
    toApp(appCode) {
      const app = this.findApp(appCode);

      //当前应用未打开
      if (!this.openApps.some(app => app.code === appCode)) {
        app && this.openApps.push(app);
      }

      //选中应用
      this.selectedKeys.splice(0, 1);
      this.selectedKeys.push(appCode);

      //激活应用并获取应用下属的菜单
      this.$store.dispatch("menu/active", appCode).then(menus => {
        this.$emit("update:menus", menus ? menus : []);
        this.$router.push(`/${app.home}`);
      });
    },

    closeApp(app) {
      //关闭应用

      const dIndex = this.currentIndex("divider");
      dIndex >= 0 && this.lockedApps.splice(dIndex, 1); //删除分割线
      this.lockedApps.splice(this.currentIndex(app.code), 1); //删除当前应用
      this.calcDivider();

      const lastApp = this.openApps[this.openApps.length - 1];
      this.toApp(lastApp.code);
    },

    lock(app, lock) {
      //锁定或解锁应用
      lockApp(app.code, lock).then(() => {
        const dIndex = this.currentIndex("divider");
        dIndex >= 0 && this.lockedApps.splice(dIndex, 1); //删除分割线
        this.lockedApps.splice(this.currentIndex(app.code), 1); //删除当前应用
        this.lockedApps.splice(this.lastIndex(lock) + 1, 0, Object.assign(app, { locked: lock })); //锁定应用最后追加当前应用，并修改锁定状态
        this.calcDivider();
      });
    },

    calcDivider() {
      //处理分割线
      const lIndex = this.lastIndex(true);
      if (lIndex >= 0 && lIndex < this.lockedApps.length - 1) {
        this.lockedApps.splice(lIndex + 1, 0, { code: "divider" }); //添加分割线
      }
    },

    currentIndex(code) {
      //当前应用索引
      return this.lockedApps.findIndex(value => value.code === code);
    },

    lastIndex(locked) {
      if (locked) {
        //最后锁定的应用索引
        let lastIndex = -1;
        this.lockedApps.forEach((app, index) => {
          if (app.global && index > lastIndex) lastIndex = index;
          if (!app.global && app.locked && index > lastIndex) lastIndex = index;
        });
        return lastIndex;
      }
      return this.lockedApps.length - 1;
    },
  },

  mounted() {
    this.toApp(this.openApps[0].code); //默认切换至第一个应用
    this.calcDivider();
  },

  created() {
    let key = window.location.pathname.split("/")[1];
    this.selectedKeys = [key];
  },

  watch: {
    $route(to) {
      const appCode = to.path.split("/")[1];
      this.toApp(appCode);
    },
  },
};
</script>
<style lang="less">
@import "~ant-design-vue/lib/style/themes/default";

@opacity-bg: 50;

/** 我的常用 */
.drop-shortcut {
  width: 100%;
  z-index: 999 !important;
  top: 52px !important;
}

/** 头部应用 */
.toplayout-menu-item {
  &.ant-menu-item,
  &.ant-menu-submenu {
    font-size: 16px;
    border: 0;
    top: 0;
    transition: color 0.1s @ease-in-out, border-color 0.1s @ease-in-out, background 0.1s @ease-in-out, padding 0.1s @ease-in-out;

    &:hover {
      border-bottom: 0px !important;
    }

    a::before {
      bottom: 0 !important;
    }

    /** 当前选中 */
    &.ant-menu-item-selected {
      border-bottom: 0px;
      a {
        color: #fff !important;
        font-weight: 500;
      }
      .icon {
        color: #ffffff5d;
        &:hover {
          color: #ffffff;
        }
      }
    }

    /** 鼠标经过 */
    &.ant-menu-item-active {
      .lockable-icon {
        display: block !important;
      }
      &:not(.ant-menu-item-selected) {
        a {
          color: @primary-color;
        }
        .icon {
          &:hover {
            color: @primary-color;
          }
        }
      }
    }
  }
}

/** 锁定应用 */
.ant-menu-vertical,
.ant-menu-horizontal {
  .toplayout-menu-item {
    margin: 0 !important;
    padding: 0 20px;
    height: 52px;
    line-height: 52px;

    .close-icon {
      font-size: 12px;
      position: absolute;
      top: 6px;
      right: -6px;
    }

    .lock-icon {
      font-size: 12px;
      position: absolute;
      bottom: 6px;
      right: -6px;
      line-height: normal;
    }
  }
}

.ant-menu-horizontal {
  border-bottom: 0px;

  /** 水平菜单分隔符 */
  .toplayout-menu-item.divider {
    padding: 0;
    div {
      border-left: 1px solid #ccc;
      height: 26px;
      margin: 13px 1px;
    }
  }
}

/** 垂直菜单分隔符 */
.ant-menu-vertical .toplayout-menu-item.divider {
  padding: 3px 20px;
  height: 3px;
  div {
    border-bottom: 1px solid #ccc;
    height: 1px;
  }
}

#top-layout {
  height: 100vh;
  overflow: auto;
  background-color: #f0f2f5;

  /** 头部区域 */
  .ant-layout-header {
    background-color: #fff;
    color: rgba(0, 0, 0, 0.65);
    height: 52px;
    padding: 0;
    display: flex;
    justify-content: space-between;
    font-size: 16px;

    /** 手机界面收缩侧边栏图标 */
    .menu-trigger {
      font-size: 16px;
      line-height: 52px;
      margin: 0 10px;
    }

    /** 左侧LOGO和我的常用 */
    .left-info {
      display: flex;
      flex: 1;

      .logo {
        width: 110px;
        text-align: center;
        line-height: 52px;
        margin: 0 5px 0 20px;
        float: left;
        img {
          width: 100%;
        }
      }

      .drop-down-menu {
        margin-right: 32px;
        cursor: pointer;
        line-height: 52px;
        .dropdown {
          transition: all 0.3s;
          transform: rotate(-180deg);
        }
        .up {
          transition: all 0.3s;
          transform: rotate(0deg);
        }

        i {
          font-size: 12px;
          margin-left: 10px;
          &:hover {
            color: @primary-color;
          }
        }
      }
    }

    /** 右侧用户信息 */
    .right-info {
      line-height: 52px;
      margin-left: 32px;
      display: flex;
      align-items: center;
      .user {
        display: flex;
        align-items: center;
        cursor: pointer;
        margin-right: 20px;
      }
    }
  }

  /** 内容区域 */
  .top-layout-content {
    height: calc(100vh - 52px);
  }
}
</style>
